module.exports = {
  isProd () {
    return process.env.NODE_ENV === 'production'
  },
  toBool (v) {
    v instanceof String && (v = v.toLowerCase())
    return v == '1' || v == 'y' || v == 'yes' || v === true || v === 'true'
  },
  isArray: ('isArray' in Array)
    ? Array.isArray
    : function (o) {
      return testTagType(o, 'Array')
    },
  isObject: function (o) {
    return testTagType(o, 'Object')
  },
  isString: function (o) {
    return testTagType(o, 'String')
  },
  isBoolean: function (o) {
    return testTagType(o, 'Boolean')
  },
  isTrue: function (o) {
    return o == true || o == 'true'
  },
  isFalse: function (o) {
    return o == false || o == 'false'
  },
  isDate: function (o) {
    return testTagType(o, 'Date')
  },
  isFunction: function (o) {
    return testTagType(o, 'Function')
  },
  isNumber: function (o) {
    return testTagType(o, 'Number')
  },
  isNumeric: function (o) {
    return !isNaN(parseFloat(o)) && isFinite(o)
  },
  isEmpty: function (o) {
    if (o === undefined || o === null || o === '' || o === 'null' || o === 'undefined') {
      return true
    }
    if (this.isArray(o) && o.length == 0) {
      return true
    }
    if (Object.keys(o).length == 0) {
      return true
    }
    return false
  },
  /**
   * 递归清除对象中所有属性值为 {},[],null,undefined,'' 的字段
   * @param {*} obj
   * @returns
   */
  clearEmptyField (obj) {
    if (obj === undefined || obj === null || obj === '') {
      return
    }
    function down (o, key, p) {
      if (Array.isArray(o)) {
        o.forEach((item, index) => {
          down(item, index, o)
        })
      } else if (o && typeof (o) === 'object') {
        Object.keys(o).forEach(k => {
          down(o[k], k, o)
        })
      }
      if (o === undefined || o === null || o === '' || (typeof (o) === 'object' && Object.keys(o).length === 0)) {
        delete p[key]
      }
    }
    if (Array.isArray(obj)) {
      obj.forEach((item, index) => {
        down(item, index, obj)
      })
    } else {
      Object.keys(obj).forEach(key => {
        down(obj[key], key, obj)
      })
    }
  },
  merge (target, ...arg) {
    return arg.reduce((acc, cur) => {
      return Object.keys(cur || {}).reduce((subAcc, key) => {
        const srcVal = cur[key]
        if (this.isObject(srcVal)) {
          subAcc[key] = this.merge(subAcc[key] ? subAcc[key] : {}, srcVal)
        } else if (this.isArray(srcVal)) {
          // series: []，下层数组直接赋值
          subAcc[key] = srcVal.map((item, idx) => {
            if (this.isObject(item)) {
              const curAccVal = subAcc[key] ? subAcc[key] : []
              return this.merge(curAccVal[idx] ? curAccVal[idx] : {}, item)
            } else {
              return item
            }
          })
        } else {
          subAcc[key] = srcVal
        }
        return subAcc
      }, acc)
    }, target)
  },
  /**
   * 转驼峰
   * @param {*} text
   * @returns
   */
  toHump (text) {
    return text.replace(/[-_](\w)/g, (_, letter) => letter.toUpperCase())
  },
  /**
   * 转大驼峰
   * @param {*} text
   * @returns
   */
  toUpperHump (text) {
    return this.toHump(text).replace(/^[a-z]/, letter => letter.toUpperCase())
  },
  /**
   * 驼峰转下划线
   * @param {*} text
   * @returns
   */
  humpToUnderline (text) {
    text = text.replace(/([A-Z])/g, '_$1').toLowerCase()
    text.startsWith('_') && (text = text.substring(1))
    return text
  },
  /**
   * 驼峰转横线
   * @param {*} text
   * @returns
   */
  humpToKebabcase (text) {
    text = text.replace(/([A-Z])/g, '-$1').toLowerCase()
    text.startsWith('-') && (text = text.substring(1))
    return text
  }
}

function testTagType (o, type) {
  return o == null || o === undefined ? false : Object.prototype.toString.call(o) === '[object ' + type + ']'
}